package com.wyw.function.learning.demo5;

import com.wyw.function.learning.common.Dish;
import com.wyw.function.learning.common.DishClient;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * @Title   使用流
 * @Description
 * @Author Mr Wu yewen.wu.china@gmail.com
 * Update History:
 * Author        Time            Content
 */
public class DemoClient9 {

    /**
     * 筛选，切片    filter
     * distinct    去重，根据hashcode和equals判断是否是同一个对象
     * limit    截断流
     * skip    返回一个抛弃了前面n个数据的流
     * @param args
     */
//    public static void main(String[] args) {
////        List<Dish> menu =
////                DishClient.getMenu();
////        // 筛选出素菜
////        List<Dish> collect = menu.stream().filter(Dish::isVegetarian).collect(Collectors.toList());
////        System.out.println(collect);
//
//        List<Integer> list = Arrays.asList(1, 2, 2, 1, 3, 3, 4, 6, 8);
////        List<Integer> collect = list.stream().filter(i -> i % 2 == 0).distinct().collect(Collectors.toList());
////        System.out.println(collect);
//
////        List<Integer> collect = list.stream().filter(i -> i % 2 == 0).limit(3).collect(Collectors.toList());
////        System.out.println(collect);
//
//        List<Integer> collect = list.stream().filter(i -> i % 2 == 0).skip(2).collect(Collectors.toList());
//        System.out.println(collect);
//
//    }

    /**
     * 映射    map
     *
     */
//    public static void main(String[] args) {
//
////        List<Dish> menu = DishClient.getMenu();
//////        List<String> collect = menu.stream().map(Dish::getName).collect(Collectors.toList());
//////        System.out.println(collect);
////
////        // 每个名字字符数
////        List<Integer> collect = menu.stream().map(Dish::getName).map(String::length).collect(Collectors.toList());
////        System.out.println(collect);
//
//        // 流的扁平化
////        List<String> list = Arrays.asList("Hello", "World");
//////        List<String[]> collect = list.stream().map(word -> word.split("")).distinct().collect(Collectors.toList());
//////        System.out.println(collect);
////
//////        List<Stream<String>> collect = list.stream().map(word -> word.split("")).map(Arrays::stream).distinct().collect(Collectors.toList());
//////        System.out.println(collect);
////
////        // 使用flatMap降将各个数据流合并起来
////        List<String> collect = list.stream().map(word -> word.split("")).flatMap(Arrays::stream).distinct().collect(Collectors.toList());
////        System.out.println(collect);
//
////        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
////        List<Integer> collect = list.stream().map(number -> number * number).collect(Collectors.toList());
////        System.out.println(collect);
//
//        List<Integer> lista = Arrays.asList(1, 2, 3);
//        List<Integer> listb = Arrays.asList(3, 4);
//        List<int[]> collect = lista.stream().flatMap(i -> listb.stream().map(j -> new int[]{i, j})).collect(Collectors.toList());
//        System.out.println(collect);
//
//    }


    /**
     * 查找，匹配    allMatch（全部匹配）、anyMatch（部分匹配）、noneMatch（都不匹配）、findFirst（第一个）、findAny（任意元素）
     */
//    public static void main(String[] args) {
//        List<Dish> menu = DishClient.getMenu();
////        if(menu.stream().anyMatch(Dish::isVegetarian)) {// allMatch    anyMatch    noneMatch    短路求值，只要一个false，就直接返回，不用处理整个流
////            System.out.println("hello");
////        }
//
////        Optional<Dish> any = menu.stream().filter(Dish::isVegetarian).findAny();
////        System.out.println(any.toString());
////        menu.stream().filter(Dish::isVegetarian).findAny().ifPresent(d-> System.out.println("Hello"));
//
//        // findFirst 在并行中限制多，如果不关心返回元素，使用findAny
//        Optional<Dish> first = menu.stream().filter(Dish::isVegetarian).findFirst();
//        if(first.isPresent()) {
//            System.out.println(first.get());
//        }
//    }

    /**
     * 规约   此类查询需要将流中所有元素反复结合起来，得到一个值
     */
    public static void main(String[] args) {
        // 将所有的数字进行相加
        List<Integer> list = Arrays.asList(1, 2, 3, 3, 4, 5, 6, 8);
//        int sum = 0;
//        for (Integer number: list)
//            sum+=number;
//
//        System.out.println(sum);

        // 使用reduce对重复应用的模式做抽象
        // reduce接收两个参数：一个初始值，一个BinaryOperate<T>来讲两个元素结合起来产生一个新的值
//        Integer reduce = list.stream().reduce(0, (a, b) -> a + b);
//        Integer reduce1 = list.stream().reduce(0, Integer::sum);
//        Integer reduce2 = list.stream().reduce(1, (a, b) -> a * b);
//        System.out.println(reduce);
//        System.out.println(reduce1);
//        System.out.println(reduce2);

        // 无初始值的情况，不接受初始值，会返回一个Optional对象
//        Optional<Integer> reduce = list.stream().reduce(Integer::sum);
//        System.out.println(reduce);

        // 最大值和最小值的情况
//        Optional<Integer> reduce = list.stream().reduce(Integer::max);
//        Optional<Integer> reduce1 = list.stream().reduce(Integer::min);
//        System.out.println(reduce);
//        System.out.println(reduce1);

        List<Dish> menu = DishClient.getMenu();
        // 菜单中菜品数量
        Integer reduce = menu.stream().map(dish -> 1).reduce(0, (a, b) -> a + b);
        System.out.println(reduce);

        // 并行处理，使用并行化可以将署入分块，分块求和，最后合并，（fork/join）
        // 使用并行有代价：传递给reduce的Lambda不能更改状态（如实例变量），而且操作必须满足结合律才可以按任意顺序执行
//        Integer reduce = menu.parallelStream().map(dish -> 1).reduce(0, (a, b) -> a + b);
//        System.out.println(reduce);



    }


}

